#pragma once
#include <QString>
#include <QIcon>
#include <QDateTime>
#include <QDateTimeEdit>
#include <QUuid>
#include "base.qpb.h"
#include <QFile>
#include <QFileInfo>
#include "../debug.h"


//创建命名空间
namespace model
{
///////////////////////////////////////////////////////////////
///工具函数
////////////////////////////////////////////////////////////////
///时间相关函数: 获取当前时间
static QString getCurrentTime()
{
    return QDateTime::fromMSecsSinceEpoch(QDateTime::currentMSecsSinceEpoch()).toString();
}

///图标相关函数: 将QByteArray转换为QIcon
static inline QIcon getIconFromByteArray(const QByteArray& bytearray)
{
    QPixmap pixmap;
    pixmap.loadFromData(bytearray);
    return QIcon(pixmap);
}

// 要求函数的定义如果写在 .h 中, 必须加 static 或者 inline (当然两个都加也可以), 避免链接阶段出现 "函数重定义" 的问题.
static inline QString formatTime(int64_t timestamp) {
    // 先把时间戳, 转换成 QDateTime 对象
    QDateTime dateTime = QDateTime::fromSecsSinceEpoch(timestamp);
    // 把 QDateTime 对象转成 "格式化时间"
    return dateTime.toString("MM-dd HH:mm:ss");
}

// 通过这个函数得到 秒级 的时间
static inline int64_t getTime() {
    return QDateTime::currentSecsSinceEpoch();
}

// 根据 QByteArray, 转成 QIcon
static inline QIcon makeIcon(const QByteArray& byteArray) {
    QPixmap pixmap;
    pixmap.loadFromData(byteArray);
    QIcon icon(pixmap);
    return icon;
}

// 读写文件操作.
// 从指定文件中, 读取所有的二进制内容. 得到一个 QByteArray
static inline QByteArray loadFileToByteArray(const QString& path) {
    QFile file(path);
    bool ok = file.open(QFile::ReadOnly);
    if (!ok) {
        LOG() << "文件打开失败!";
        return QByteArray();
    }
    QByteArray content = file.readAll();
    file.close();
    return content;
}

// 把 QByteArray 中的内容, 写入到某个指定文件里
static inline void writeByteArrayToFile(const QString& path, const QByteArray& content) {
    QFile file(path);
    bool ok = file.open(QFile::WriteOnly);
    if (!ok) {
        LOG() << "文件打开失败!";
        return;
    }
    file.write(content);
    file.flush();
    file.close();
}
///////////////////////////////////////////////////////////////
///用户信息: 用户id, 昵称, 个性签名, 头像, 电话号
///////////////////////////////////////////////////////////////
///
class UserInfo{
public:
    QString userId;        //用户编号
    QString userName;      //用户昵称
    QString userSignature; //用户签名
    QString userPhone;     //用户电话
    QIcon userIcon;        //用户头像

    void load(const bite_im::UserInfo& userInfo);
};

///////////////////////////////////////////////////////////////
///消息类型
///////////////////////////////////////////////////////////////
enum MessageType{
    TEXT_TYPE = 1,          //文本类型
    IMAGE_TYPE,             //图片类型
    FILE_TYPE,              //文件类型
    SPEECH_TYPE,            //语音类型
    UNKNOWN_TYPE             //未知类型
};

///////////////////////////////////////////////////////////////
///消息信息: 消息发送者, 消息发送时间, 消息发送类型, 消息发送内容, 消息自身编号, 消息所属会话编号
/// 此外, 应当还有文件id和文件name属性, 方便非文本类型的消息使用,如果消息为文本类型则无效
///////////////////////////////////////////////////////////////
class Message{
public:
    static QString makeId()
    {
        return "M:" + QUuid::createUuid().toString().sliced(25,12);
    }

    static Message makeTextMessage(const UserInfo& userinfo,const QByteArray& content,const QString& messionid)
    {
        Message message;
        message.sender = userinfo;              //消息发送者
        message.sendTime = getCurrentTime();    //消息发送时间
        message.messageType = TEXT_TYPE;        //消息类型
        message.fileId = "";                    //文件id
        message.fileName = "";                  //文件name
        message.messageContent = content;       //消息内容
        message.messageId = makeId();           //消息id
        message.SessionId = messionid;          //消息所属会话id
        return message;
    }
    static Message makeImageMessage(const UserInfo& userinfo,const QByteArray& content,const QString& messionid)
    {
        Message message;
        message.sender = userinfo;              //消息发送者
        message.sendTime = getCurrentTime();    //消息发送时间
        message.messageType = IMAGE_TYPE;        //消息类型
        message.fileId = "";                    //文件id
        message.fileName = "";                  //文件name
        message.messageContent = content;       //消息内容
        message.messageId = makeId();           //消息id
        message.SessionId = messionid;          //消息所属会话id
        return message;
    }
    static Message makeFileMessage(const UserInfo& userinfo,const QByteArray& content,const QString& messionid,const QString& extrainfo)
    {
        Message message;
        message.sender = userinfo;              //消息发送者
        message.sendTime = getCurrentTime();    //消息发送时间
        message.messageType = FILE_TYPE;        //消息类型
        message.fileId = "";                    //文件id
        //extra
        message.fileName = extrainfo;           //文件name
        message.messageContent = content;       //消息内容
        message.messageId = makeId();           //消息id
        message.SessionId = messionid;          //消息所属会话id

        return message;
    }
    static Message makeSpeechMessage(const UserInfo& userinfo,const QByteArray& content,const QString& messionid)
    {
        Message message;
        message.sender = userinfo;              //消息发送者
        message.sendTime = getCurrentTime();    //消息发送时间
        message.messageType = SPEECH_TYPE;        //消息类型
        message.fileId = "";                    //文件id
        message.fileName = "";                  //文件name
        message.messageContent = content;       //消息内容
        message.messageId = makeId();           //消息id
        message.SessionId = messionid;          //消息所属会话id
        return message;
    }

    static Message makeMessage(const UserInfo& userinfo, MessageType messagetype, const QByteArray& content, const QString& messionid, const QString& extrainfo)
    {
        switch(messagetype)
        {
        case model::MessageType::TEXT_TYPE :
            return makeTextMessage(userinfo,content, messionid);

        case model::MessageType::IMAGE_TYPE :
            return makeImageMessage(userinfo,content, messionid);

        case model::MessageType::FILE_TYPE :
            return makeFileMessage(userinfo, content, messionid,extrainfo);

        case model::MessageType::SPEECH_TYPE :
            return makeSpeechMessage(userinfo, content, messionid);
        default:
            return Message();
        }
    }

public:
    UserInfo sender;        //消息发送者
    QString sendTime = "";     //消息发送时间
    MessageType messageType = TEXT_TYPE; //消息类型
    QString fileId = "";                 //文件id
    QString fileName = "";               //文件name
    QByteArray messageContent;           //消息内容
    QString messageId;			 //消息id
    QString SessionId;			 //消息所属会话id

    void load(const bite_im::MessageInfo& pbMessageInfo);
};

///////////////////////////////////////////////////////////////
///会话类型: 会话编号, 名称, 头像, 会话内用户id, 会话的最后一条消息
///////////////////////////////////////////////////////////////
class ChatSessionInfo{
public:
    QString SessionId;        //会话编号
    QString SessionName;      //会话名称
    QIcon SessionIcon;        //会话头像
    QString SessionUserId = "";    //会话内包含用户
    Message lastMesssage;

    void load(const bite_im::ChatSessionInfo& sessionInfo);
};
///////////////////////////////////////////////////////////////
///从protobuf中加载数据到本地
///////////////////////////////////////////////////////////////
inline void UserInfo::load(const bite_im::UserInfo &pbUserInfo)
{
    userId = pbUserInfo.userId();                                //用户编号
    userName= pbUserInfo.nickname();                             //用户昵称
    userSignature = pbUserInfo.description();                    //用户签名
    userPhone = pbUserInfo.phone();                              //用户电话
    userIcon = getIconFromByteArray(pbUserInfo.avatar());        //用户头像
}

inline void Message::load(const bite_im::MessageInfo &pbMessageInfo)
{
    messageId = pbMessageInfo.messageId();			 //消息id
    SessionId = pbMessageInfo.chatSessionId();			 //消息所属会话id
    sendTime = QDateTime::fromMSecsSinceEpoch(pbMessageInfo.timestamp()).toString();//消息发送时间
    sender.load(pbMessageInfo.sender());        //消息发送者
    //这里使用一个自动类型转换获取type, 根据type来做出不同行为
    auto type =  pbMessageInfo.message().messageType(); //消息类型

    switch(type)
    {
    case bite_im::MessageTypeGadget::MessageType::STRING:
    {
        messageType = TEXT_TYPE;
        messageContent = pbMessageInfo.message().stringMessage().content().toUtf8();
    }
    break;
    case bite_im::MessageTypeGadget::MessageType::IMAGE:
    {
        messageType = IMAGE_TYPE;
        if(pbMessageInfo.message().imageMessage().hasFileId()) fileId = pbMessageInfo.message().imageMessage().fileId();
        if(pbMessageInfo.message().imageMessage().hasImageContent()) messageContent = pbMessageInfo.message().imageMessage().imageContent();
    }
    break;
    case bite_im::MessageTypeGadget::MessageType::FILE:
    {
        messageType = FILE_TYPE;
        if(pbMessageInfo.message().fileMessage().hasFileId()) fileId = pbMessageInfo.message().fileMessage().fileId();
        fileName = pbMessageInfo.message().fileMessage().fileName();
        if(pbMessageInfo.message().fileMessage().hasFileContents()) messageContent = pbMessageInfo.message().fileMessage().fileContents();

    }
    break;
    case bite_im::MessageTypeGadget::MessageType::SPEECH:
    {
        messageType = SPEECH_TYPE;
        if(pbMessageInfo.message().speechMessage().hasFileId()) fileId = pbMessageInfo.message().speechMessage().fileId();
        if(pbMessageInfo.message().speechMessage().hasFileContents()) fileId = pbMessageInfo.message().speechMessage().fileContents();
    }
    break;
    }
}

inline void ChatSessionInfo::load(const bite_im::ChatSessionInfo &chatSessionInfo)
{
    if(chatSessionInfo.hasSingleChatFriendId()) SessionUserId = chatSessionInfo.singleChatFriendId();
    SessionId = chatSessionInfo.chatSessionId();
    SessionName = chatSessionInfo.chatSessionName();
    if(chatSessionInfo.hasPrevMessage()) lastMesssage.load(chatSessionInfo.prevMessage());
    if(chatSessionInfo.hasAvatar()) SessionIcon = getIconFromByteArray(chatSessionInfo.avatar());
}
} // end namespace








